﻿using System;
using System.Globalization;
namespace Sherwood.SignOn
{
    public interface IUserAccount
    {
        /// <summary>
        /// Primary key for user account.
        /// </summary>
        Guid Id { get; }

        /// <summary>
        /// Account username. This value should be unique for each account and treated as non-case sensitive.
        /// </summary>
        string UserName { get;  }

        /// <summary>
        /// Password hash represented in the following format:
        ///     algorithmName:hash
        ///     e.g. SHA256:[hash data]
        /// </summary>
        string PasswordHash { get;  }

        /// <summary>
        /// User first name.
        /// </summary>
        string FirstName { get;  }

        /// <summary>
        /// User last name.
        /// </summary>
        string LastName { get; }

        /// <summary>
        /// User gender.
        /// </summary>
        Gender Gender { get;  }


        DateTime? DateOfBirth { get;  }

        /// <summary>
        /// Account email address. Note that this is a unique field. 
        /// No two accounts should share the same email address.
        /// </summary>
        string Email { get;  }

        /// <summary>
        /// Email account the user wishes to change to
        /// </summary>
        string ProposedEmail { get; }

        /// <summary>
        /// Account mobile number
        /// </summary>
        string Mobile { get; }

        /// <summary>
        /// .Net culture name for the user's preferred language.
        /// </summary>
        string CultureName1 { get;  }

        /// <summary>
        /// .Net culture name for the user's second preference for language.
        /// </summary>
        string CultureName2 { get; }

        /// <summary>
        /// .Net culture name for the user's third preference for language.
        /// </summary>
        string CultureName3 { get; }


        /// <summary>
        /// ISO2 country code
        /// </summary>
        string Country { get;  }

        /// <summary>
        /// Date account was created
        /// </summary>
        DateTime DateCreated { get; }

        /// <summary>
        /// Date account was last modified
        /// </summary>
        DateTime DateModified { get; }

        /// <summary>
        /// Indicates the verification status of the account.
        ///     Unverified: the account has not been verified
        ///     Verified: the account has been verified
        ///     ResetPassword: the account has been verified, but the user has requested a new verification code
        /// in order to reset the password.
        /// </summary>
        VerificationStatus VerificationStatus { get;  }

        /// <summary>
        /// Url requested prior to creating a user account, or requesting a password reset. 
        /// This can be used to automatically redirect the user to their desired destination.
        /// </summary>
        string RequestedUrl { get;  }

        string VerificationCode { get;  }

        /// <summary>
        /// Specifies where the user account is enabled. Note that this is distinct from verification status.
        /// If an account is not enabled it usually means that the account has been disabled by as system
        /// administrator.
        /// </summary>
        bool IsEnabled { get;  }


        /// <summary>
        /// Generates a verification code (which an be used for verifying a user via an email link).
        /// The VerificationCode property is set, but this method does not change VerificationStatus.
        /// Usually, VerificationStatus should be changed at the same time.
        /// </summary>
        /// <returns></returns>
        string CreateVerificationCode();

        /// <summary>
        /// Validates the verification code against the code stored in the VerificationCode property for the user.
        /// Verification status is not changed as part of this operation, but should usually be changed to "Verified"
        /// as part of a verification process.
        /// </summary>
        /// <param name="verificationCode"></param>
        /// <returns></returns>
        bool ValidateVerificationCode(string verificationCode);

        /// <summary>
        /// Validates the verification code against the code stored in the VerificationCode property for the user and 
        /// sets the user's email / password to the proposed email / password.
        /// </summary>
        /// <param name="verificationCode"></param>
        /// <returns></returns>
        bool ValidateProposedEmailAndPasswordChange(string verificationCode);


        /// <summary>
        /// Modifies the verificationStatus and requestedUrl and verificationCode
        /// </summary>
        /// <param name="verificationStatus"></param>
        /// <param name="requestedUrl"></param>
        void SetVerificationParameters(VerificationStatus verificationStatus, string requestedUrl, string verificationCode);

        /// <summary>
        /// Creates a SHA256 hash for the specified password and sets the PasswordHash property.
        /// </summary>
        /// <param name="password">Password to be hashed.</param>
        /// <returns>True if hash was sucessfully created, False if an error occured or password was invalid (e.g. null).</returns>
        bool SetPassword(string password);

        /// <summary>
        /// Creates a SHA256 hash for the specified password and sets the ProposedPasswordHash property and
        /// ProposedEmailProperty as well as generating a new verification code.
        /// This can be used to allow users request a password / email change, which is then verified via email.
        /// </summary>
        /// <param name="password">Password to be hashed.</param>
        /// <param name="email">New email address</param>
        /// <returns>Verification code if hash was sucessfully created, null if an error occured or password was invalid (e.g. null).</returns>
        string SetProposedEmailAndPassword(string email, string password);

        /// <summary>
        /// Verifies the specified password against the PasswordHash property.
        /// </summary>
        /// <param name="password">Password to be validated</param>
        /// <returns>True if password corrosponds to the PasswordHash, False if password does not match or an error occured.</returns>
        bool VerifyPassword(string password);


        /// <summary>
        /// User display name in the form: FirstName LastName
        /// </summary>
        string DisplayName {get;}




        /// <summary>
        /// Sets the IsEnabled property of a user account to enabled or disabled.
        /// </summary>
        /// <param name="enabled">True to enable, False to disable</param>
        void SetEnabled(bool enabled);
    }
}
